import 'dart:async';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_demo/ex/object.dart';
import 'package:flutter_demo/pages/page_with_title.dart';
import 'package:flutter_demo/widgets/app_widgets.dart';
import 'package:intl/intl.dart';
import 'package:uuid/uuid.dart';

class FlutterChannelPage extends PageWithTitle {
  const FlutterChannelPage({super.key})
      : super("与原生平台通讯(BasicMessageChannel、MethodChannel、EventChannel)");

  @override
  List<Widget> buildContentWidgets(BuildContext context) {
    return const [
      PrimaryTitle("简介"),
      BodyText("Flutter是如何与原生平台通讯的？"),
      //是用dart语言写的代码，运行在虚拟机（Dart VM），它通过C++实现的Flutter Engi
      LabelText("FlutterEngine，是我们在原生平台可以看到自动生成的Flutter相关对象。"
          "Flutter引擎基于C++实现，编译成各个平台的共享库如android(.so)、ios(.dylib)、"
          "windows(.dll)进行互相调用，以此实现与各个原生平台通讯。"),
      AppSpacer.normal,
      LabelText("Flutter引擎包含三个重要组成部分："),
      LabelText("- Dart VM，执行dart代码的虚拟机"),
      LabelText("- 渲染引擎，复制UI渲染（Impeller、Skia）"),
      LabelText("- 平台桥接层，通过如jni等技术，实现dart与原生平台代码通讯"),
      LabelText("在Android平台上dart与java/kotlin通讯需经历以下过程：dart->Dart VM->"
          "Flutter Engine->jni->Java/Kotlin"),
      AppSpacer.normal,
      BodyText("Flutter提供了Channel API用于实现dart与原生平台的通讯，内部封装了数据序列化"
          "（二进制、json）和调用过程，可以快速实现与原生平台方法互调"),
      LabelText("数据类型映射："),
      UrlLink(
        "dart与java kotlin Obj-C swift C C++数据类型映射",
        "https://docs.flutter.dev/platform-integration/platform-channels#codec",
      ),
      NoticeText("因为存在大量的模板代码，有个第三方插件pigeon可以通过配置的方式自动生成模板"
          "代码"),
      AppSpacer.large,
      _BasicExample(),
      UlItem("BasicMessageChannel"),
      BodyText("基础消息通道，用于dart与平台原生语言通信，他可以实现所有双端通讯场景"),
      PrimaryHeaderLabelText(
        "name",
        "通道名称，作为通道的唯一id，一般以 包名/模块/方法 来命名，这样可以避免与"
            "第三方包冲突",
      ),
      PrimaryHeaderLabelText(
        "codec",
        "编解码器，负责参数与返回值的序列化与反序列化，在Flutter中已经有几种默认实现",
        "         - StandardMessageCodec，标准的消息编解码，参数与返回值都是由支持的数据"
            "类型构成复杂对象",
        "         - BinaryCodec，用于传输字节数组，对应java ByteBuffer，常用于图片数据之"
            "类的缓冲区传输",
        "         - StringCodec，用于传输字符串，如果是为了方便查看数据，也可以将对象转成"
            "Json字符串来互相传递",
        "         - JSONMessageCodec，基于StringCodec封装，可以将对象序列化成字符串传输"
            "，然后接收时反序列化成Json对象",
      ),
      PrimaryHeaderLabelText(
        "send",
        "发送消息，对方可以通过setMessageHandler注册消息处理器",
      ),
      PrimaryHeaderLabelText(
        "setMessageHandler",
        "注册消息处理器，当对方调用时通过注册的监听实现调用处理，当不再需要时设置为null即可",
      ),
      AppSpacer.large,

      _MethodExample(),
      UlItem("MethodChannel"),
      BodyText("方法通道，与BasicMessageChannel类似，但他在使用上更像后台接口请求，常常用于"
          "请求响应的场景"),
      PrimaryHeaderLabelText(
        "name",
        "通道名称，作为通道的唯一id，一般以 包名/模块 来命名，方法名在调用时指定，在同个模块的"
            "增删改查等多个方法时通过这种方式就无需写多个BasicMessageChannel",
      ),
      PrimaryHeaderLabelText(
        "invokeMethod",
        "调用方法，需指定方法名，原生平台实现时根据方法名来执行不同的处理，可选传参",
      ),
      PrimaryHeaderLabelText(
        "setMethodCallHandler",
        "注册方法调用处理器，根据调用方的方法类型来分情况处理，返回有未实现、成功、错误三种调用，"
            "根据情况使用",
      ),
      AppSpacer.large,

      _EventExample(),
      UlItem("EventChannel"),
      BodyText("事件通道，在需要持续订阅状态变化时可用"),
      PrimaryHeaderLabelText(
        "name",
        "通道名称，作为通道的唯一id，一般以 包名/事件名称 来命名",
      ),
      PrimaryHeaderLabelText(
        "receiveBroadcastStream",
        "Flutter平台订阅事件",
      ),
      PrimaryHeaderLabelText(
        "setStreamHandler",
        "原生平台设置流处理器，回调发送数据流需要在主线程中执行",
      ),
    ];
  }
}

class _BasicExample extends StatefulWidget {
  const _BasicExample();

  @override
  State<StatefulWidget> createState() {
    return _BasicExampleState();
  }
}

class _BasicExampleState extends State<_BasicExample> {
  final _typeTestMessageChannel = const BasicMessageChannel(
      "com.example.flutter_demo/type_test", StandardMessageCodec());
  late Future _flutterCall;
  var platformCall;

  @override
  void initState() {
    super.initState();
    _flutterCall = _typeTestMessageChannel.send({
      "bool": true,
      "int": 1,
      "long": 1 + 100000000000,
      "double": 0.00000001,
      "String": "from flutter",
      "Uint8List": Uint8List.fromList(List.generate(10, (index) => index)),
      "Int32List":
          Int32List.fromList(List.generate(5, (index) => index + 1000)),
      "Int64List":
          Int64List.fromList(List.generate(3, (index) => index + 100000000000)),
      "Float32List":
          Float32List.fromList(List.generate(3, (index) => index + 0.000001)),
      "Float64List":
          Float64List.fromList(List.generate(3, (index) => index + 0.00000001)),
      "List": List.generate(10, (index) => index.toString()),
      "Map": {"key": "value"},
    });
    _typeTestMessageChannel.setMessageHandler((platformArguments) {
      print(platformArguments.toString());
      setState(() {
        platformCall = platformArguments.toString();
      });
      return Future.value(null);
    });
  }

  @override
  void dispose() {
    _typeTestMessageChannel.setMessageHandler(null);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        FutureBuilder(
          future: _flutterCall,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Text("waiting...");
            }
            snapshot.error?.let((it) {
              print(it.toString());
            });
            return Text(snapshot.data?.toString() ?? "no result");
          },
        ),
        if (platformCall != null) Text("调用次数：$platformCall"),
      ],
    );
  }
}

class _MethodExample extends StatefulWidget {
  const _MethodExample();

  @override
  State<StatefulWidget> createState() {
    return _MethodExampleState();
  }
}

class _MethodExampleState extends State<_MethodExample> {
  final _methodChannel =
      const MethodChannel("com.example.flutter_demo/method_call");
  int? value;

  @override
  void initState() {
    super.initState();
    _methodChannel.invokeMethod("getValue").then(
          (currValue) => setState(() {
            value = currValue;
          }),
        );
    _methodChannel.setMethodCallHandler((methodCall) {
      return Future.value(null);
    });
  }

  @override
  void dispose() {
    _methodChannel.setMethodCallHandler(null);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Wrap(
      crossAxisAlignment: WrapCrossAlignment.center,
      children: [
        OutlinedButton(
            onPressed: () {
              _methodChannel.invokeMethod("add", -1).then(
                    (currValue) => setState(() {
                      value = currValue;
                    }),
                  );
            },
            child: const Text("减")),
        if (value != null)
          Padding(
            padding: const EdgeInsetsDirectional.symmetric(horizontal: 10),
            child: Text("$value"),
          ),
        OutlinedButton(
            onPressed: () {
              _methodChannel.invokeMethod("add", 1).then(
                    (currValue) => setState(() {
                      value = currValue;
                    }),
                  );
            },
            child: const Text("加")),
      ],
    );
  }
}

class _EventExample extends StatelessWidget {
  const _EventExample();

  final _eventListener =
      const EventChannel("com.example.flutter_demo/timeChanged");

  @override
  Widget build(BuildContext context) {
    final timeFormater = DateFormat("yyyyMMdd HH:mm:ss").format;
    const uuid = Uuid();
    return StreamBuilder(
        stream: _eventListener.receiveBroadcastStream(uuid.v4()),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.none ||
              snapshot.connectionState == ConnectionState.waiting) {
            return const Text("waiting...");
          }
          return Text(
              timeFormater(DateTime.fromMillisecondsSinceEpoch(snapshot.data)));
        });
  }
}
